package com.googlecode.cpbi.test.function;

import java.util.ArrayList;
import java.util.List;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleListener;
import org.springframework.core.io.Resource;
import org.springframework.osgi.test.platform.OsgiPlatform;

import com.googlecode.cpbi.test.BaseTestCase;
import com.googlecode.cpbi.util.BundleManifest;
import com.googlecode.cpbi.util.FileUtils;
import com.googlecode.cpbi.util.Osgi;
import com.googlecode.cpbi.util.DefaultOsgi;

/**
 * @author Jeremy Wales
 */
public abstract class AcceptanceTestCase extends BaseTestCase {
	Osgi osgi;
	OsgiPlatform osgiPlatform;

	protected void setUp() throws Exception {
		super.setUp();
		osgiPlatform = getOsgiPlatform();
		osgiPlatform.getConfigurationProperties().setProperty("org.osgi.framework.bootdelegation", "sun.*");
		osgiPlatform.start();
		osgi = new DefaultOsgi(osgiPlatform.getBundleContext());
	}

	protected abstract OsgiPlatform getOsgiPlatform();

	protected void tearDown() throws Exception {
		super.tearDown();
		osgiPlatform.stop();
	}

	public void testInstallerIsInvokedAndWorksInTheOsgiFramework() throws Exception {
		ExportBundleEventCollecter exportBundleEventCollecter = new ExportBundleEventCollecter();
		osgi.register(exportBundleEventCollecter);
		Resource cpbiJar = FileUtils.getResourcesMatching("file:" + System.getProperty("user.dir") + "/**/*.jar")[0];
		osgi.installBundleFrom(cpbiJar.getURL().toString()).start();
		waitForExportBundleToReach(BundleEvent.INSTALLED, exportBundleEventCollecter);
		assertSame(getClass(), installAndStartImportingBundle().loadClass(getClass().getName()));
	}

	private Bundle installAndStartImportingBundle() throws BundleException {
		BundleManifest testManifest = new BundleManifest();
		testManifest.setSymbolicName(getClass().getName() + ".import");
		testManifest.setImportPackage("org.apache.commons.lang," + getClass().getPackage().getName());
		Bundle bundle = osgi.installEmptyBundleAround(testManifest.getManifest(), "test:" + getClass().getName());
		bundle.start();
		return bundle;
	}

	private void waitForExportBundleToReach(int bundleEventType, ExportBundleEventCollecter exportBundleEventCollecter)
			throws Exception {
		int checks = 0;
		int checkLimit = 100;
		Integer awaitedEventType = new Integer(bundleEventType);
		while (!exportBundleEventCollecter.events.contains(awaitedEventType)) {
			if (++checks > checkLimit)
				fail("Export Bundle did not reach BundleEvent type '" + awaitedEventType + "'.");
			Thread.sleep(100);
		}
	}

	private boolean isExportBundle(Bundle bundle) {
		return "com.googlecode.cpbi.export".equals(bundle.getSymbolicName());
	}

	private class ExportBundleEventCollecter implements BundleListener {
		public List events = new ArrayList();

		public void bundleChanged(BundleEvent event) {
			if (isExportBundle(event.getBundle())) {
				events.add(new Integer(event.getType()));
			}
		}
	}
}
